package org.xq.shop.maxaishop.service.impl;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.xq.shop.maxaishop.conf.XqConstants;
import org.xq.shop.maxaishop.dao.XqSpkieDao;
import org.xq.shop.maxaishop.entity.XqSpkie;
import org.xq.shop.maxaishop.service.XqCommodityService;
import org.xq.shop.maxaishop.service.XqSpkieService;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Calendar;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * (XqSpkie)表服务实现类
 *
 * @author makejava
 * @since 2021-06-19 11:28:30
 */
@Service("xqSpkieService")
public class XqSpkieServiceImpl implements XqSpkieService {
    @Resource
    private XqSpkieDao xqSpkieDao;
    @Resource
    private XqCommodityService xqCommodityService;
    @Resource
    private RedisTemplate redisTemplate;


    /**
     * 预加载今天的秒杀商品库存到redis做缓存
     */
    @Scheduled(cron = "0 0 */1 * * ?")
    @PostConstruct
    public void preLoadTodaySpkies() {
        String today = DateFormatUtils.format(Calendar.getInstance().getTime(), "yyyy-MM-dd");
        List<XqSpkie> xqSpkies = this.selectToDay(today);
        Set<String> repeatkeys = redisTemplate.keys(XqConstants.MAXAISHOP_SPKIE_REPEAT_ORDER+"*");
        //清空重复提交的数据
        redisTemplate.delete(repeatkeys);
        Set<String> keys = redisTemplate.keys(XqConstants.MAXAISHOP_SPKIE_ORDER_STATUS+"*");
        //重置redis中的订单状态数据
        redisTemplate.delete(keys);
        System.out.println("已清空数据");
        for (XqSpkie item : xqSpkies) {
            Integer spkieLimit = item.getSpkieLimit();//秒杀商品库存
            //先删除已有的库存
            if (redisTemplate.hasKey(XqConstants.MAXAISHOP_SPKIE_STORE + item.getSpkieId() + ":" + item.getCid())) {
                redisTemplate.delete(XqConstants.MAXAISHOP_SPKIE_STORE + item.getSpkieId() + ":" + item.getCid());
            }
            //检查如果没有库存数据, 则加入商品库存
            //将秒杀商品库存放入redis库中
            redisTemplate.opsForValue().increment(XqConstants.MAXAISHOP_SPKIE_STORE + item.getSpkieId() + ":" + item.getCid(), spkieLimit + 0L);
            //检查redis中是否有当前秒杀活动的订单序号，如果存在重置和设置过期时间
            if (redisTemplate.hasKey(XqConstants.MAXAISHOP_SPKIE_ORDER_NUM +item.getSpkieId())) {
                //清除秒杀订单序号
                redisTemplate.delete(XqConstants.MAXAISHOP_SPKIE_ORDER_NUM  +item.getSpkieId());
                //重新计数
                redisTemplate.opsForValue().increment(XqConstants.MAXAISHOP_SPKIE_ORDER_NUM +item.getSpkieId(), 0l);
                //设置过期时间，1天
                redisTemplate.expire(XqConstants.MAXAISHOP_SPKIE_ORDER_NUM +item.getSpkieId(), 1, TimeUnit.DAYS);
            }
            //删除订单状态
            redisTemplate.delete(XqConstants.MAXAISHOP_SPKIE_ORDER_STATUS + item.getSpkieId());
        }
    }

    /**
     * 通过ID查询单条数据
     *
     * @param spkieId 主键
     * @return 实例对象
     */
    @Override
    public XqSpkie queryById(Integer spkieId) {
        return this.xqSpkieDao.queryById(spkieId);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit  查询条数
     * @return 对象列表
     */
    @Override
    public List<XqSpkie> queryAllByLimit(int offset, int limit) {
        return this.xqSpkieDao.queryAllByLimit(offset, limit);
    }

    /**
     * 新增数据
     *
     * @param xqSpkie 实例对象
     * @return 实例对象
     */
    @Override
    public XqSpkie insert(XqSpkie xqSpkie) {
        this.xqSpkieDao.insert(xqSpkie);
        //将秒杀商品库存放入redis库中
        redisTemplate.opsForValue().increment(XqConstants.MAXAISHOP_SPKIE_STORE + xqSpkie.getSpkieId() + ":" + xqSpkie.getCid(), xqSpkie.getSpkieLimit()+0L);
        //清除秒杀缓存
        Set keys = redisTemplate.keys("spkies::*");//删除秒杀商品缓存
        redisTemplate.delete(keys);
        return xqSpkie;
    }

    /**
     * 修改数据
     *
     * @param xqSpkie 实例对象
     * @return 实例对象
     */
    @Override
    public XqSpkie update(XqSpkie xqSpkie) {
        this.xqSpkieDao.update(xqSpkie);
        return this.queryById(xqSpkie.getSpkieId());
    }

    /**
     * 通过主键删除数据
     *
     * @param spkieId 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer spkieId) {
        return this.xqSpkieDao.deleteById(spkieId) > 0;
    }

    @Override
    public List<XqSpkie> selectAll(Integer start, Integer end) {
        return this.xqSpkieDao.selectAll(start,end);
    }

    @Override
    public int selectCount() {
        return this.xqSpkieDao.selectCount();
    }

    //添加缓存
    @Cacheable(cacheNames = "spkies", key = "#toDay")
    @Override
    public List<XqSpkie> selectToDay(String toDay) {
        return this.xqSpkieDao.selectToDay(toDay);

    }

    @Override
    public XqSpkie selectMs(Integer spkieId) {
        return this.xqSpkieDao.selectMs(spkieId);
    }

    @Override
    public int updateSales(int aid) {
        return this.xqSpkieDao.updateSales(aid);
    }



    /**
     * 定时任务，每天0点检查已结束的秒杀商品库存，还原到商品库存中
     */
    @Scheduled(cron = "0 1 0 * * ?")
    public void returnStock() {
        List<XqSpkie> xqSpkies = xqSpkieDao.selectOverSeckill();
        for (XqSpkie xqSpky : xqSpkies) {
            xqCommodityService.updateCount(xqSpky.getSpkieLimit(),xqSpky.getCid());
            System.out.println(xqSpky);
            xqSpky.setSpkieLimit(0);
            xqSpkieDao.update(xqSpky);
        }
    }
}
